<!-- 我的地图 -->

<template>
  <div class="MyMap" @mouseleave="mouseleave" @mousemove="mousemove">
    <div ref="map" class="MyMap-render" />

    <div class="MyMap-floor" @mouseenter="canAdd = false" @mouseleave="canAdd = true">
      <div
        v-for="item in floors"
        :key="item.id"
        :class="{ 'floor-current': current === item.id }"
        @click="changeFloor(item.id)"
      >
        {{ item.name }}
      </div>
    </div>

    <div class="MyMap-cursor">
      <img
        v-for="item in CORE.DICT.SUB_SYSTEM"
        :key="item[0]"
        :src="getImg(item[2], '_map')"
        :class="{ 'cursor-current': addSystemId === item[0] }"
        :style="cursorStyle"
      />
    </div>
  </div>
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import CONST from './CONST'

const ENGINE = CORE.common('js/Engine3.1.js')

// ============================== 导出组件 ============================== //

export default {
  /**
   * 名称定义 (实际使用名称)
   */
  name: 'MyMap',

  /**
   * 混入列表 (配置选项合并)
   */
  mixins: [CORE.mixWeb(), CORE.mixTree(), CORE.mixSelect()],

  /**
   * 状态数据 (函数返回对象)
   */
  data() {
    return {
      engine: null, // 地图引擎
      current: CONST.FLOOR[0].id, // 当前楼层
      popId: '', // 气泡 ID
      cursorStyle: null, // 指针样式
      canAdd: false, // 是否可添加
    }
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    /**
     * 楼层列表
     */
    floors() {
      const { list } = this
      return CONST.FLOOR.map((floor) => {
        const hideList = list.filter((item) => floor.id !== item.site.floor)
        const showList = list.filter((item) => floor.id === item.site.floor)
        return {
          ...floor,
          deviceHide: hideList.map((item) => item.id),
          deviceShow: showList.map((item) => item.id),
        }
      })
    },

    /**
     * 正在增加的子系统 ID
     */
    addSystemId() {
      const { isAdd, one, param } = this
      return isAdd && one.deviceId ? param.subSystemId : ''
    },

    /**
     * 加载完成的列表就绪
     */
    mountedReadyList() {
      return this.engine ? this.readyList : false
    },
  },

  /**
   * 监听属性 (深度 deep 首次 immediate)
   */
  watch: {
    /**
     * 监听子系统 ID
     */
    'param.subSystemId'(subSystemId) {
      if (subSystemId) {
        this.startList()
      } else {
        this.delLayer()
        this.setList()
      }
      this.setModal()
      this.setOne()
    },

    /**
     * 监听加载完成的列表就绪
     */
    async mountedReadyList(ready) {
      if (ready) {
        this.delLayer()
        await this.$nextTick()
        this.addLayer()

        this.addModelList()
        await this.$nextTick()
        this.addPopList()

        this.setModal()
        this.changeFloor(this.current)

        // console.log(this.list)
        // if (this.list.length) {
        //   this.engine.Api.Camera.lookAt({
        //     objType: CONST.ID,
        //     id: this.list[0].id,
        //     click: true,
        //     offset: new this.engine.Api.Type.Vector3(0, 0, 30),
        //     time: 0.3,
        //   })
        // }
      }
    },

    /**
     * 监听新增就绪
     */
    readyAdd(ready) {
      if (ready) {
        this.setModal()
        this.setOne()
      }
    },

    /**
     * 监听删除就绪
     */
    readyDel(ready) {
      if (ready) {
        this.setModal()
        this.setOne()
      }
    },

    /**
     * 监听单项，隐藏气泡
     */
    'one.id'(id) {
      const { popId } = this
      const popDiv = document.getElementsByClassName('MyMap-pop')
      if (popId && popId !== id && popDiv && popDiv.length) popDiv[0].style.display = 'none'
    },
  },

  /**
   * 挂载完成 (先抽取再调用)
   */
  mounted() {
    this.initEngine()
  },

  /**
   * 销毁之前 (先抽取再调用)
   */
  beforeDestroy() {
    this.engine.dispose()
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 初始化引擎
     */
    async initEngine() {
      await CORE.loadJS(ENGINE, '地图引擎')

      const engine = new window.Engine({ ...CONST.ENGINE, dom: this.$refs.map })
      this.engine = engine

      engine.open()
      engine.on('MeshClick', this.toAdd)
      engine.on('MeshRightClick', this.cancleAdd)
      engine.on('EngineFinish', () => {
        const { MeshInfo } = engine.Api
        MeshInfo.setVisible({ objType: CONST.DEFAULT, id: ['Louding', 'zai', 'Guangzhu'], visible: false }) // 楼顶，光柱
        this.flyTo(CONST.POINT, CONST.TARGET)
      })
    },

    /**
     * 添加区域设备
     */
    toAdd(layerObject, pointStr) {
      const { isAdd, one, current: floor, param, startAdd } = this
      if (isAdd && one.deviceId) {
        const [layer, bind] = layerObject.split(':')
        const { EPSGType, x, y, z, zone } = JSON.parse(pointStr)
        const [, , icon = '', moreHeight = 0] = CORE.DICT.SUB_SYSTEM.find(([id]) => id === param.subSystemId) || []
        const siteJson = JSON.stringify({ layer, bind, EPSGType, zone, floor, icon })
        CORE.merge(one, { longitude: `${x}`, latitude: `${y}`, elevation: `${z + moreHeight}`, siteJson })
        startAdd()
      }
    },

    /**
     * 取消添加
     */
    cancleAdd() {
      this.setModal()
      this.setOne()
      this.selectParam.areaId = ''
    },

    /**
     * 飞往目标
     */
    flyTo(point, target, time = 0) {
      const { Type, Camera } = this.engine.Api
      Camera.flyTo({
        point: new Type.Vector3(...point),
        target: new Type.Vector3(...target),
        time,
      })
    },

    /**
     * 切换楼层
     */
    changeFloor(id) {
      const floor = this.floors.find((item) => item.id === id)
      this.current = floor.id

      const { MeshInfo } = this.engine.Api
      MeshInfo.setVisible({ objType: CONST.DEFAULT, id: floor.hide, visible: false })
      MeshInfo.setVisible({ objType: CONST.DEFAULT, id: floor.show, visible: true })
      MeshInfo.setVisible({ objType: CONST.ID, id: floor.deviceHide, visible: false })
      MeshInfo.setVisible({ objType: CONST.ID, id: floor.deviceShow, visible: true })
    },

    /**
     * 添加图层
     */
    addLayer() {
      if (!this.engine) return
      this.engine.Api.Layers.addLayer({ ...CONST.LAYER, id: CONST.ID })
    },

    /**
     * 删除图层
     */
    delLayer() {
      if (!this.engine) return
      this.engine.Api.Layers.removeLayer({ id: CONST.ID })
      CONST.ID++ // 更新图层 ID
    },

    /**
     * 添加模型列表
     */
    async addModelList() {
      this.list.forEach((item) => {
        const { id, deviceName: name, longitude: x, latitude: y, elevation: z, site } = item
        const shape = new this.engine.Api.Type.Vector3(Number(x), Number(y), Number(z))
        const userData = { ...CONST.MODEL, id, name, assetPath: site.icon, shapes: [shape] }
        this.engine.Api.Models.addModel({ objType: CONST.ID, modelType: 'Obj', userData })
      })
    },

    /**
     * 添加气泡列表
     */
    async addPopList() {
      const { engine, list, treeMap } = this
      list.forEach((item) => {
        const { id, deviceName: name, areaId } = item
        engine.Api.Pop.setPop({ objType: CONST.ID, id }, (result) => {
          this.popId = id
          this.setOne(item)

          const panelDiv = document.createElement('div')
          const nameDiv = document.createElement('div')
          const areaDiv = document.createElement('div')
          const delBtn = document.createElement('button')
          panelDiv.className = 'MyMap-pop'
          nameDiv.innerText = name
          areaDiv.innerText = treeMap[areaId].nameList.join(' > ')
          delBtn.innerText = '删除'
          delBtn.onclick = () => {
            this.setModal('del')
            this.startDel()
          }
          panelDiv.appendChild(nameDiv)
          panelDiv.appendChild(areaDiv)
          panelDiv.appendChild(delBtn)
          result.appendChild(panelDiv)
        })
      })
    },

    /**
     * 鼠标移动
     */
    mousemove(e) {
      this.cursorStyle = this.canAdd ? { left: `${e.x}px`, top: `${e.y}px` } : null
    },

    /**
     * 鼠标离开
     */
    mouseleave() {
      this.cursorStyle = null
    },

    /**
     * 获取图片
     */
    getImg(img, suffix = '') {
      return require(`./img/${img}${suffix}.png`)
    },
  },
}
</script>
